package com.qd.panda.service.commodity;

import cn.hutool.core.util.URLUtil;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.commodity.CommodityClassificationListDTO;
import com.qd.common.panda.domain.entity.commodity.CommodityDTO;
import com.qd.common.panda.domain.entity.commodity.CommodityDescDTO;
import com.qd.common.panda.domain.entity.stroke.UserStrokeOrderMallCardInfoDTO;
import com.qd.panda.model.*;
import com.qd.panda.service.stroke.order.UserStrokeOrderMallCardInfoService;
import com.qd.panda.service.stroke.order.UserStrokeOrderMallService;
import com.qd.system.util.FileConfirmUtil;
import com.qd.upload.config.UploadDTO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Safelist;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 处理数据中心同步的数据
 *
 * @author sjk
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CommodityDcService {
    private final CommodityService commodityService;
    private final CommodityDescService commodityDescService;
    private final CommodityPicService commodityPicService;
    private final CommodityClassificationListService commodityClassificationListService;
    private final UserStrokeOrderMallService userStrokeOrderMallService;
    private final UserStrokeOrderMallCardInfoService userStrokeOrderMallCardInfoService;
    private final ObjectMapper objectMapper;
    private final UploadDTO uploadDTO;

    @Value("${dc.url}")
    private String url;

    @SneakyThrows
    public void syncData(String json) {
        JsonNode jsonNode = objectMapper.readTree(json);
        JsonNode incrementalSyncNode = jsonNode.get("incrementalSync");
        if (null == incrementalSyncNode) {
            log.error("数据异常,json: {}", json);
            return;
        }
        JsonNode commodityListNode = jsonNode.get("commodityList");
        if (null == commodityListNode) {
            log.error("数据异常,json: {}", json);
            return;
        }
        List<CommodityDTO> list = objectMapper.readValue(commodityListNode.toString(), new TypeReference<>() {
        });

        List<Commodity> commodityList = new ArrayList<>(1024);
        List<CommodityDesc> commodityDescList = new ArrayList<>(1024);
        List<CommodityPic> commodityPicList = new ArrayList<>(1024);
        List<CommodityClassificationList> commodityClassificationList = new ArrayList<>(1024);

        for (CommodityDTO commodityDTO : list) {
            List<CommodityPic> picList = commodityDTO.getPicList().stream().map(picDTO -> {
                CommodityPic commodityPic = commodityPicService.dtoToModel(picDTO);
                commodityPic.setPicPath(savePic(picDTO.getPicPathDisplay()));
                return commodityPic;
            }).collect(Collectors.toList());
            commodityPicList.addAll(picList);
            CommodityDescDTO commodityDesc = commodityDTO.getCommodityDesc();
            buildCommodityDesc(commodityDesc);
            commodityDescList.add(commodityDescService.dtoToModel(commodityDesc));
            Commodity commodity = commodityService.dtoToModel(commodityDTO);
            commodity.setCommodityPic(commodityDTO.getCommodityPicDisplay());
            commodity.setCombinedCommodity(null == commodityDTO.getCombinedCommodity() ? ConstantDto.SF0 : commodityDTO.getCombinedCommodity());
            commodity.setUserPrice(getUserDiscountPrice(commodityDTO));
            if (StringUtils.hasLength(commodityDTO.getCommodityPicDisplay())) {
                commodity.setCommodityPic(savePic(commodityDTO.getCommodityPicDisplay()));
            }
            List<CommodityClassificationListDTO> classificationList = commodityDTO.getClassificationList();
            if (!classificationList.isEmpty()) {
                commodityClassificationList.addAll(commodityClassificationListService.dtoToModelList(classificationList));
            }
            commodityList.add(commodity);
        }
        boolean all;
        int incrementalSync = incrementalSyncNode.intValue();
        if (incrementalSync == 1) {
            all = false;
        } else if (incrementalSync == 2) {
            commodityService.removeAll();
            commodityDescService.removeAll();
            commodityPicService.removeAll();
            commodityClassificationListService.removeAll();
            all = true;
        } else {
            log.error("incrementalSync值异常: {}", incrementalSync);
            return;
        }
        save(commodityList, commodityDescList, commodityPicList, commodityClassificationList, all);
    }

    private void buildCommodityDesc(CommodityDescDTO commodityDesc) {
        if (StringUtils.hasLength(commodityDesc.getCommodityDesc())) {
            Document document = Jsoup.parse(commodityDesc.getCommodityDesc());
            Elements images = document.getElementsByTag("img");
            for (Element img : images) {
                String imgUrl = img.attr("src");
                img.attr("src", FileConfirmUtil.getImageFile(savePic(imgUrl)));
            }
            commodityDesc.setCommodityDesc(Jsoup.clean(document.outerHtml(), Safelist.relaxed()));
        }
    }

    private String savePic(String picPath) {
        String fileUrl = url + picPath.substring(picPath.indexOf("sys") - 1);
        if(log.isDebugEnabled()) {
            log.debug("fileUrl： {}", fileUrl);
        }
        String image = picPath.substring(picPath.indexOf("image"));
        File file = new File(uploadDTO.getOfficialPath() + image);
        try (InputStream stream = URLUtil.getStream(URLUtil.url(fileUrl))) {
            cn.hutool.core.io.FileUtil.writeFromStream(stream, file);
        } catch (IOException e) {
            throw new ApiException(e);
        }
        return File.separator + image;
    }

    private void save(List<Commodity> commodityList, List<CommodityDesc> commodityDescList, List<CommodityPic> commodityPicList, List<CommodityClassificationList> commodityClassificationList, boolean all) {
        if (null != commodityList && !commodityList.isEmpty()) {
            if (all) {
                commodityService.saveCommodityList(commodityList);
            } else {
                commodityService.saveOrUpdateCommodityList(commodityList);
            }
        }
        if (null != commodityDescList && !commodityDescList.isEmpty()) {
            if (all) {
                commodityDescService.saveCommodityDescList(commodityDescList);
            } else {
                commodityDescService.saveOrUpdateCommodityDescList(commodityDescList);
            }
        }
        if (null != commodityPicList && !commodityPicList.isEmpty()) {
            if (all) {
                commodityPicService.saveCommodityPicList(commodityPicList);
            } else {
                commodityPicService.saveOrUpdateCommodityPicList(commodityPicList);
            }
        }
        if (null != commodityClassificationList && !commodityClassificationList.isEmpty()) {
            if (all) {
                commodityClassificationListService.saveCommodityClassificationList(commodityClassificationList);
            } else {
                commodityClassificationListService.saveOrUpdateCommodityClassificationList(commodityClassificationList);
            }
        }
    }


    private static BigDecimal getUserDiscountPrice(CommodityDTO commodity) {
        if (commodity.getUserDiscountMethods().equals(PandaConstant.DISCOUNT_METHODS_1)) {
            return commodity.getCommodityPrice().multiply(commodity.getUserDiscountValue()).divide(new BigDecimal("100"), 3, RoundingMode.HALF_UP);
        } else {
            return commodity.getUserDiscountValue();
        }
    }

    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public void syncCardInfo(String json) {
        JsonNode dataNode = objectMapper.readTree(json);
        for (JsonNode jsonNode : dataNode) {
            JsonNode orderIdNode = jsonNode.get("orderId");
            if (null == orderIdNode) {
                return;
            }
            String orderId = orderIdNode.asText();
            UserStrokeOrderMall userStrokeOrderMall = userStrokeOrderMallService.getById(orderId);
            if (null == userStrokeOrderMall) {
                return;
            }
            JsonNode cardInfoIdNode = jsonNode.get("cardInfoId");

            if (!userStrokeOrderMallCardInfoService.isExists(cardInfoIdNode.asText())) {
                UserStrokeOrderMallCardInfoDTO userStrokeOrderMallCardInfo = new UserStrokeOrderMallCardInfoDTO();
                userStrokeOrderMallCardInfo.setCardInfoId(cardInfoIdNode.asText());
                JsonNode cardNode = jsonNode.get("cardNo");
                if (null != cardNode) {
                    userStrokeOrderMallCardInfo.setCardNo(cardNode.asText());
                }
                JsonNode pwdNode = jsonNode.get("pwd");
                JsonNode expireTimeNode = jsonNode.get("expireTime");
                if (null != pwdNode) {
                    userStrokeOrderMallCardInfo.setCardPwd(pwdNode.asText());
                }
                if (null != expireTimeNode) {
                    userStrokeOrderMallCardInfo.setExpireTime(expireTimeNode.asText());
                }
                userStrokeOrderMallCardInfo.setOrderId(userStrokeOrderMall.getOrderId());
                userStrokeOrderMallCardInfoService.save(userStrokeOrderMallCardInfo);
                userStrokeOrderMallCardInfo.freeData();
            }
            userStrokeOrderMall.freeData();
        }
    }
}
